<!DOCTYPE html>
<html lang="zh-CN">
<head>
  <meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=2">
<meta name="theme-color" content="#222">
<meta name="generator" content="Hexo 5.4.2">
  <link rel="apple-touch-icon" sizes="180x180" href="/images/apple-touch-icon-next.png">
  <link rel="icon" type="image/png" sizes="32x32" href="/images/favicon-32x32-next.png">
  <link rel="icon" type="image/png" sizes="16x16" href="/images/favicon-16x16-next.png">
  <link rel="mask-icon" href="/images/logo.svg" color="#222">

<link rel="stylesheet" href="/css/main.css">


<link rel="stylesheet" href="/lib/font-awesome/css/font-awesome.min.css">

<script id="hexo-configurations">
    var NexT = window.NexT || {};
    var CONFIG = {"hostname":"eryangz.gitee.io","root":"/","scheme":"Gemini","version":"7.8.0","exturl":false,"sidebar":{"position":"left","display":"post","padding":18,"offset":12,"onmobile":false},"copycode":{"enable":true,"show_result":true,"style":"mac"},"back2top":{"enable":true,"sidebar":false,"scrollpercent":true},"bookmark":{"enable":false,"color":"#222","save":"auto"},"fancybox":false,"mediumzoom":false,"lazyload":false,"pangu":false,"comments":{"style":"tabs","active":null,"storage":true,"lazyload":false,"nav":null},"algolia":{"hits":{"per_page":10},"labels":{"input_placeholder":"Search for Posts","hits_empty":"We didn't find any results for the search: ${query}","hits_stats":"${hits} results found in ${time} ms"}},"localsearch":{"enable":true,"trigger":"auto","top_n_per_article":1,"unescape":false,"preload":false},"motion":{"enable":true,"async":false,"transition":{"post_block":"fadeIn","post_header":"slideDownIn","post_body":"slideDownIn","coll_header":"slideLeftIn","sidebar":"slideUpIn"}},"path":"search.xml"};
  </script>

  <meta name="description" content="FLASK常用库和插件JWT认证JSON Web Token（JWT）是一个非常轻巧的规范。这个规范允许我们使用JWT在两个组织之间传递安全可靠的信息。JSON Web Signature是一个有着简单的统一表达形式的字符串: Header.Payload.Signature">
<meta property="og:type" content="article">
<meta property="og:title" content="FLASK常用库和插件">
<meta property="og:url" content="https://eryangz.gitee.io/20211120/FLASK%E5%B8%B8%E7%94%A8%E5%BA%93%E5%92%8C%E6%8F%92%E4%BB%B6/index.html">
<meta property="og:site_name" content="二扬">
<meta property="og:description" content="FLASK常用库和插件JWT认证JSON Web Token（JWT）是一个非常轻巧的规范。这个规范允许我们使用JWT在两个组织之间传递安全可靠的信息。JSON Web Signature是一个有着简单的统一表达形式的字符串: Header.Payload.Signature">
<meta property="og:locale" content="zh_CN">
<meta property="article:published_time" content="2021-11-20T12:20:56.000Z">
<meta property="article:modified_time" content="2023-05-20T09:39:59.303Z">
<meta property="article:author" content="二扬">
<meta property="article:tag" content="flask">
<meta name="twitter:card" content="summary">

<link rel="canonical" href="https://eryangz.gitee.io/20211120/FLASK%E5%B8%B8%E7%94%A8%E5%BA%93%E5%92%8C%E6%8F%92%E4%BB%B6/">


<script id="page-configurations">
  // https://hexo.io/docs/variables.html
  CONFIG.page = {
    sidebar: "",
    isHome : false,
    isPost : true,
    lang   : 'zh-CN'
  };
</script>

  <title>FLASK常用库和插件 | 二扬</title>
  






  <noscript>
  <style>
  .use-motion .brand,
  .use-motion .menu-item,
  .sidebar-inner,
  .use-motion .post-block,
  .use-motion .pagination,
  .use-motion .comments,
  .use-motion .post-header,
  .use-motion .post-body,
  .use-motion .collection-header { opacity: initial; }

  .use-motion .site-title,
  .use-motion .site-subtitle {
    opacity: initial;
    top: initial;
  }

  .use-motion .logo-line-before i { left: initial; }
  .use-motion .logo-line-after i { right: initial; }
  </style>
</noscript>

</head>

<body itemscope itemtype="http://schema.org/WebPage">
  <div class="container use-motion">
    <div class="headband"></div>

    <header class="header" itemscope itemtype="http://schema.org/WPHeader">
      <div class="header-inner"><div class="site-brand-container">
  <div class="site-nav-toggle">
    <div class="toggle" aria-label="切换导航栏">
      <span class="toggle-line toggle-line-first"></span>
      <span class="toggle-line toggle-line-middle"></span>
      <span class="toggle-line toggle-line-last"></span>
    </div>
  </div>

  <div class="site-meta">

    <a href="/" class="brand" rel="start">
      <span class="logo-line-before"><i></i></span>
      <h1 class="site-title">二扬</h1>
      <span class="logo-line-after"><i></i></span>
    </a>
      <p class="site-subtitle" itemprop="description">blog</p>
  </div>

  <div class="site-nav-right">
    <div class="toggle popup-trigger">
        <i class="fa fa-search fa-fw fa-lg"></i>
    </div>
  </div>
</div>




<nav class="site-nav">
  <ul id="menu" class="menu">
        <li class="menu-item menu-item-home">

    <a href="/" rel="section"><i class="fa fa-fw fa-home"></i>首页</a>

  </li>
        <li class="menu-item menu-item-about">

    <a href="/about/" rel="section"><i class="fa fa-fw fa-user"></i>关于</a>

  </li>
        <li class="menu-item menu-item-tags">

    <a href="/tags/" rel="section"><i class="fa fa-fw fa-tags"></i>标签</a>

  </li>
        <li class="menu-item menu-item-categories">

    <a href="/categories/" rel="section"><i class="fa fa-fw fa-th"></i>分类</a>

  </li>
        <li class="menu-item menu-item-archives">

    <a href="/archives/" rel="section"><i class="fa fa-fw fa-archive"></i>归档</a>

  </li>
      <li class="menu-item menu-item-search">
        <a role="button" class="popup-trigger"><i class="fa fa-search fa-fw"></i>搜索
        </a>
      </li>
  </ul>
</nav>



  <div class="search-pop-overlay">
    <div class="popup search-popup">
        <div class="search-header">
  <span class="search-icon">
    <i class="fa fa-search"></i>
  </span>
  <div class="search-input-container">
    <input autocomplete="off" autocapitalize="off"
           placeholder="搜索..." spellcheck="false"
           type="search" class="search-input">
  </div>
  <span class="popup-btn-close">
    <i class="fa fa-times-circle"></i>
  </span>
</div>
<div id="search-result">
  <div id="no-result">
    <i class="fa fa-spinner fa-pulse fa-5x fa-fw"></i>
  </div>
</div>

    </div>
  </div>

</div>
    </header>

    
  <div class="back-to-top">
    <i class="fa fa-arrow-up"></i>
    <span>0%</span>
  </div>
  <div class="reading-progress-bar"></div>


    <main class="main">
      <div class="main-inner">
        <div class="content-wrap">
          

          <div class="content post posts-expand">
            

    
  
  
  <article itemscope itemtype="http://schema.org/Article" class="post-block" lang="zh-CN">
    <link itemprop="mainEntityOfPage" href="https://eryangz.gitee.io/20211120/FLASK%E5%B8%B8%E7%94%A8%E5%BA%93%E5%92%8C%E6%8F%92%E4%BB%B6/">

    <span hidden itemprop="author" itemscope itemtype="http://schema.org/Person">
      <meta itemprop="image" content="/images/avatar.jpg">
      <meta itemprop="name" content="二扬">
      <meta itemprop="description" content="念念不忘, 必有回响">
    </span>

    <span hidden itemprop="publisher" itemscope itemtype="http://schema.org/Organization">
      <meta itemprop="name" content="二扬">
    </span>
      <header class="post-header">
        <h1 class="post-title" itemprop="name headline">
          FLASK常用库和插件
        </h1>

        <div class="post-meta">
            <span class="post-meta-item">
              <span class="post-meta-item-icon">
                <i class="fa fa-calendar-o"></i>
              </span>
              <span class="post-meta-item-text">发表于</span>

              <time title="创建时间：2021-11-20 20:20:56" itemprop="dateCreated datePublished" datetime="2021-11-20T20:20:56+08:00">2021-11-20</time>
            </span>
              <span class="post-meta-item">
                <span class="post-meta-item-icon">
                  <i class="fa fa-calendar-check-o"></i>
                </span>
                <span class="post-meta-item-text">更新于</span>
                <time title="修改时间：2023-05-20 17:39:59" itemprop="dateModified" datetime="2023-05-20T17:39:59+08:00">2023-05-20</time>
              </span>
            <span class="post-meta-item">
              <span class="post-meta-item-icon">
                <i class="fa fa-folder-o"></i>
              </span>
              <span class="post-meta-item-text">分类于</span>
                <span itemprop="about" itemscope itemtype="http://schema.org/Thing">
                  <a href="/categories/flask/" itemprop="url" rel="index"><span itemprop="name">flask</span></a>
                </span>
            </span>

          <br>
            <span class="post-meta-item" title="本文字数">
              <span class="post-meta-item-icon">
                <i class="fa fa-file-word-o"></i>
              </span>
                <span class="post-meta-item-text">本文字数：</span>
              <span>8.3k</span>
            </span>
            <span class="post-meta-item" title="阅读时长">
              <span class="post-meta-item-icon">
                <i class="fa fa-clock-o"></i>
              </span>
                <span class="post-meta-item-text">阅读时长 &asymp;</span>
              <span>8 分钟</span>
            </span>

        </div>
      </header>

    
    
    
    <div class="post-body" itemprop="articleBody">

      
        <h1 id="FLASK常用库和插件"><a href="#FLASK常用库和插件" class="headerlink" title="FLASK常用库和插件"></a>FLASK常用库和插件</h1><h2 id="JWT认证"><a href="#JWT认证" class="headerlink" title="JWT认证"></a>JWT认证</h2><h3 id="JSON-Web-Token（JWT）是一个非常轻巧的规范。这个规范允许我们使用JWT在两个组织之间传递安全可靠的信息。JSON-Web-Signature是一个有着简单的统一表达形式的字符串-Header-Payload-Signature"><a href="#JSON-Web-Token（JWT）是一个非常轻巧的规范。这个规范允许我们使用JWT在两个组织之间传递安全可靠的信息。JSON-Web-Signature是一个有着简单的统一表达形式的字符串-Header-Payload-Signature" class="headerlink" title="JSON Web Token（JWT）是一个非常轻巧的规范。这个规范允许我们使用JWT在两个组织之间传递安全可靠的信息。JSON Web Signature是一个有着简单的统一表达形式的字符串: Header.Payload.Signature"></a>JSON Web Token（JWT）是一个非常轻巧的规范。这个规范允许我们使用JWT在两个组织之间传递安全可靠的信息。JSON Web Signature是一个有着简单的统一表达形式的字符串: Header.Payload.Signature</h3><span id="more"></span>

<h5 id="头部（Header）"><a href="#头部（Header）" class="headerlink" title="头部（Header）"></a>头部（Header）</h5><p>头部用于描述关于该JWT的最基本的信息，例如其类型以及签名所用的算法等。 JSON内容要经Base64 编码生成字符串成为Header。</p>
<h5 id="载荷（PayLoad）"><a href="#载荷（PayLoad）" class="headerlink" title="载荷（PayLoad）"></a>载荷（PayLoad）</h5><p>payload的五个字段都是由JWT的标准所定义的。</p>
<ol>
<li>iss: 该JWT的签发者</li>
<li>sub: 该JWT所面向的用户</li>
<li>aud: 接收该JWT的一方</li>
<li><strong>exp(expires): 什么时候过期，这里是一个Unix时间戳</strong></li>
<li>iat(issued at): 在什么时候签发的</li>
</ol>
<p>后面的信息可以按需补充。 JSON内容要经Base64 编码生成字符串成为PayLoad。</p>
<h5 id="签名（signature）"><a href="#签名（signature）" class="headerlink" title="签名（signature）"></a>签名（signature）</h5><p>这个部分header与payload通过header中声明的加密方式，使用密钥secret进行加密，生成签名。 JWS的主要目的是保证了数据在传输过程中不被修改，验证数据的完整性。但由于仅采用Base64对消息内容编码，因此不保证数据的不可泄露性。所以不适合用于传输敏感数据。</p>
<h3 id="JWT的Python库"><a href="#JWT的Python库" class="headerlink" title="JWT的Python库"></a>JWT的Python库</h3><h4 id="itsdangerous"><a href="#itsdangerous" class="headerlink" title="itsdangerous"></a>itsdangerous</h4><ul>
<li>JSONWebSignatureSerializer</li>
<li>TimedJSONWebSignatureSerializer （可设置有效期）<h4 id="pyjwt"><a href="#pyjwt" class="headerlink" title="pyjwt"></a>pyjwt</h4>安装pyjwt<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">pip install pyjwt</span><br></pre></td></tr></table></figure></li>
</ul>
<p>flask封装生成jwt token和验证jwt token </p>
<figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> jwt</span><br><span class="line"><span class="keyword">from</span> flask <span class="keyword">import</span> current_app</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">def</span> <span class="title">generate_jwt</span>(<span class="params">payload, expiry, secret=<span class="literal">None</span></span>):</span></span><br><span class="line">    <span class="string">&quot;&quot;&quot;</span></span><br><span class="line"><span class="string">    生成jwt</span></span><br><span class="line"><span class="string">    :param payload: dict 载荷</span></span><br><span class="line"><span class="string">    :param expiry: datetime 有效期</span></span><br><span class="line"><span class="string">    :param secret: 密钥</span></span><br><span class="line"><span class="string">    :return: jwt</span></span><br><span class="line"><span class="string">    &quot;&quot;&quot;</span></span><br><span class="line">    _payload = &#123;<span class="string">&#x27;exp&#x27;</span>: expiry&#125;</span><br><span class="line">    _payload.update(payload)</span><br><span class="line"></span><br><span class="line">    <span class="keyword">if</span> <span class="keyword">not</span> secret:</span><br><span class="line">        secret = current_app.config[<span class="string">&#x27;JWT_SECRET&#x27;</span>]</span><br><span class="line"></span><br><span class="line">    token = jwt.encode(_payload, secret, algorithm=<span class="string">&#x27;HS256&#x27;</span>)</span><br><span class="line">    <span class="keyword">return</span> token.decode()</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">def</span> <span class="title">verify_jwt</span>(<span class="params">token, secret=<span class="literal">None</span></span>):</span></span><br><span class="line">    <span class="string">&quot;&quot;&quot;</span></span><br><span class="line"><span class="string">    检验jwt</span></span><br><span class="line"><span class="string">    :param token: jwt</span></span><br><span class="line"><span class="string">    :param secret: 密钥</span></span><br><span class="line"><span class="string">    :return: dict: payload</span></span><br><span class="line"><span class="string">    &quot;&quot;&quot;</span></span><br><span class="line">    <span class="keyword">if</span> <span class="keyword">not</span> secret:</span><br><span class="line">        secret = current_app.config[<span class="string">&#x27;JWT_SECRET&#x27;</span>]</span><br><span class="line"></span><br><span class="line">    <span class="keyword">try</span>:</span><br><span class="line">        payload = jwt.decode(token, secret, algorithm=[<span class="string">&#x27;HS256&#x27;</span>])</span><br><span class="line">    <span class="keyword">except</span> jwt.PyJWTError:</span><br><span class="line">        payload = <span class="literal">None</span></span><br><span class="line"></span><br><span class="line">    <span class="keyword">return</span> payload</span><br></pre></td></tr></table></figure>

<h2 id="Flask-Script"><a href="#Flask-Script" class="headerlink" title="Flask-Script"></a>Flask-Script</h2><p>安装</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">pip install Flask-Script</span><br></pre></td></tr></table></figure>

<p>使用</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line">from flask_script import Manager.</span><br><span class="line"></span><br><span class="line">app = Flask(__name__)</span><br><span class="line"></span><br><span class="line">manager = Manager(app) # 使用Manager对象管理app对象</span><br><span class="line"></span><br><span class="line">if __name__ == &#x27;__main__&#x27;:</span><br><span class="line">    manager.run()</span><br></pre></td></tr></table></figure>

<p>配置启动参数</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">runserver -h 0.0.0.0 -p 5000</span><br></pre></td></tr></table></figure>

<h2 id="Flask-migrate"><a href="#Flask-migrate" class="headerlink" title="Flask-migrate"></a>Flask-migrate</h2><p>安装</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">pip install flask-migrate</span><br></pre></td></tr></table></figure>
<p>终端报错解决</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">Error: Could not locate a Flask application.	# 没有设置好flaskapp的环境变量</span><br><span class="line"></span><br><span class="line">set FLASK_APP=sql_alchemy_bili</span><br></pre></td></tr></table></figure>

<p>由于 Flask-Script 长久不维护，且没有适配flask 2.0 以上的版本， 所以 flask-migrate 去掉了 Flask-Script 的支持</p>
<ul>
<li><p>老本版的使用</p>
<figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># db_manager.py</span></span><br><span class="line"><span class="keyword">from</span> flask <span class="keyword">import</span> Flask</span><br><span class="line"><span class="keyword">from</span> flask_migrate <span class="keyword">import</span> Migrate, MigrateCommand</span><br><span class="line"><span class="keyword">from</span> flask_script <span class="keyword">import</span> Manager</span><br><span class="line"><span class="keyword">from</span> app.comm <span class="keyword">import</span> db</span><br><span class="line"><span class="keyword">from</span> app.comm <span class="keyword">import</span> config, get_app_env</span><br><span class="line"><span class="keyword">from</span> app.models <span class="keyword">import</span> *</span><br><span class="line"></span><br><span class="line">app_env = get_app_env()  <span class="comment"># 获取当前的环境变量</span></span><br><span class="line"></span><br><span class="line">app = Flask(__name__)</span><br><span class="line">app.config.from_object(config[app_env])</span><br><span class="line">db.init_app(app)  <span class="comment"># linux服务器必须添加</span></span><br><span class="line">migrate = Migrate(app, db)</span><br><span class="line">manager = Manager(app)</span><br><span class="line">manager.add_command(<span class="string">&#x27;db&#x27;</span>, MigrateCommand)</span><br><span class="line"></span><br><span class="line"><span class="keyword">if</span> __name__ == <span class="string">&#x27;__main__&#x27;</span>:</span><br><span class="line">    manager.run()</span><br><span class="line"></span><br></pre></td></tr></table></figure></li>
<li><p>执行命令<code>python db_manager.py db init 、python db_manager.py db migrate、python db_manager.py db upgrade</code></p>
</li>
<li><p>flask_migrate==3.1.0新版本的使用</p>
<figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># app.py </span></span><br><span class="line"><span class="keyword">from</span> flask <span class="keyword">import</span> Flask</span><br><span class="line"><span class="keyword">from</span> flask_migrate <span class="keyword">import</span> Migrate</span><br><span class="line"><span class="keyword">from</span> app.comm <span class="keyword">import</span> db</span><br><span class="line"><span class="keyword">from</span> app.comm <span class="keyword">import</span> config, get_app_env</span><br><span class="line"><span class="keyword">from</span> app.models <span class="keyword">import</span> *</span><br><span class="line"></span><br><span class="line">app_env = get_app_env()</span><br><span class="line"></span><br><span class="line">app = Flask(__name__)</span><br><span class="line">app.config.from_object(config[app_env])</span><br><span class="line">db.init_app(app)  </span><br><span class="line">migrate = Migrate(app, db)</span><br></pre></td></tr></table></figure></li>
<li><p>执行命令：<code>flask db init 、flask db migrate、flask db upgrade</code></p>
</li>
</ul>
<h2 id="Flask-SQLalchemy"><a href="#Flask-SQLalchemy" class="headerlink" title="Flask-SQLalchemy"></a>Flask-SQLalchemy</h2><p>安装</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">pip install Flask-SQLAlchemy</span><br></pre></td></tr></table></figure>

<p>使用</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">app = Flask(__name__)</span><br><span class="line"></span><br><span class="line">db = SQLAlchemy(app)	# 直接绑定app</span><br><span class="line"></span><br><span class="line">db = SQLAlchemy()	# 初始化对象后绑定app</span><br><span class="line">db.init_app(app)</span><br></pre></td></tr></table></figure>

<p>关系型字段定义：</p>
<figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># 一对多</span></span><br><span class="line">student_id = db.Column(db.Integer, db.ForeignKey(<span class="string">&#x27;student.id&#x27;</span>)) <span class="comment"># 多</span></span><br><span class="line"></span><br><span class="line">grade_ids = db.relationship(<span class="string">&#x27;Grade&#x27;</span>, uselist=<span class="literal">True</span>, backref=<span class="string">&#x27;student&#x27;</span>) <span class="comment"># 一</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># 一访问多</span></span><br><span class="line">学生.grade_ids</span><br><span class="line"><span class="comment"># 多访问一</span></span><br><span class="line">成绩.student</span><br></pre></td></tr></table></figure>

<p>增：</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line">单独操作    </span><br><span class="line">	db.session记录数据库菜操作</span><br><span class="line">    user = User(mobile=&#x27;15612345678&#x27;, name=&#x27;itcast&#x27;)</span><br><span class="line">    db.session.add(user)</span><br><span class="line">    db.session.commit()</span><br><span class="line">    profile = Profile(id=user.id)</span><br><span class="line">    db.session.add(profile)</span><br><span class="line">    db.session.commit()</span><br><span class="line">对于批量添加也可使用如下语法</span><br><span class="line">    db.session.add_all([user1, user2, user3])</span><br><span class="line">    db.session.commit()</span><br></pre></td></tr></table></figure>

<p>删：</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line">方式一</span><br><span class="line">    user = User.query.order_by(User.id.desc()).first()</span><br><span class="line">    db.session.delete(user)</span><br><span class="line">    db.session.commit()</span><br><span class="line">方式二</span><br><span class="line">    User.query.filter(User.mobile=&#x27;18512345678&#x27;).delete()</span><br><span class="line">    db.session.commit()</span><br></pre></td></tr></table></figure>

<p>改:</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line">方式一</span><br><span class="line">    user = User.query.get(1)</span><br><span class="line">    user.name = &#x27;Python&#x27;</span><br><span class="line">    db.session.add(user)</span><br><span class="line">    db.session.commit()</span><br><span class="line">方式二</span><br><span class="line">    User.query.filter_by(id=1).update(&#123;&#x27;name&#x27;:&#x27;python&#x27;&#125;)</span><br><span class="line">    User.query.filter(id==1).update(&#123;&#x27;name&#x27;: &#x27;哈哈&#x27;&#125;)</span><br><span class="line">    db.session.commit()</span><br></pre></td></tr></table></figure>

<p>查:</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br></pre></td><td class="code"><pre><span class="line">查询对象</span><br><span class="line">    Model.query.all()</span><br><span class="line">    Model.query.first()</span><br><span class="line">    Model.query.get(PK)</span><br><span class="line">    db.session.query(Model).all()</span><br><span class="line">    db.session.query(Model).first()</span><br><span class="line">    db.session.query(Model).get(2)</span><br><span class="line">    </span><br><span class="line">过滤 filter_by(只有and查询，等直查询)  filter</span><br><span class="line">    User.query.filter(User.name==&#x27;eryang&#x27;).first()</span><br><span class="line">    User.query.filter_by(mobile=&#x27;18208333774&#x27;).first() </span><br><span class="line">    </span><br><span class="line">逻辑与</span><br><span class="line">    from sqlalchemy import and_</span><br><span class="line">    User.query.filter(User.mobile==&#x27;18208333774&#x27;, User.name==&#x27;eryang&#x27;).all()</span><br><span class="line">    User.query.filter_by(mobile=&#x27;18208333774&#x27;, name=&#x27;eryang&#x27;).all()           </span><br><span class="line">逻辑或</span><br><span class="line">    from sqlalchemy import or_</span><br><span class="line">    User.query.filter(or_(User.id==&#x27;1&#x27;, User.name==&#x27;eryang&#x27;)).all()</span><br><span class="line">    </span><br><span class="line">逻辑非</span><br><span class="line">    from sqlalchemy import not_</span><br><span class="line">    User.query.filter(not_(User.name==&#x27;eryang&#x27;)).limit(3).all()</span><br><span class="line">    </span><br><span class="line">偏移 offset</span><br><span class="line">    User.query.filter(not_(User.name==&#x27;eryang&#x27;)).offset(3).all()</span><br><span class="line">    </span><br><span class="line">限制 limit</span><br><span class="line">    User.query.filter(not_(User.name==&#x27;eryang&#x27;)).limit(3).all()</span><br><span class="line">    </span><br><span class="line">排序 order_by</span><br><span class="line">	    User.query.filter(not_(User.name==&#x27;eryang&#x27;)).order_by(User.id.desc()).limit(3).all()</span><br><span class="line">	User.query.filter(not_(User.name==&#x27;eryang&#x27;)).order_by(User.id).limit(3).all()</span><br><span class="line">    </span><br><span class="line">复合查询</span><br><span class="line">User.query.filter(not_(User.name==&#x27;eryang&#x27;)).order_by(User.id).offset(2).limit(3).all()</span><br><span class="line"></span><br><span class="line">优化查询 </span><br><span class="line">    from sqlalchemy.orm import load_only</span><br><span class="line">    User.query.options(load_only(User.name, User.mobile)).filter(not_(User.name==&#x27;eryang&#x27;)).first()</span><br><span class="line">    </span><br><span class="line">聚合查询</span><br><span class="line">    from sqlalchemy import func</span><br><span class="line">    &quot;select user_id, count(target_user_id) from user_relation group by user_id&quot;</span><br><span class="line">    db.session.query(Relation.user_id, func.count(Relation.target_user_id)).group_by(Relation.user_id).all()</span><br><span class="line">    </span><br><span class="line">关联查询</span><br><span class="line">    1. 使用ForeignKey</span><br><span class="line">    	从表指定foreignkey  表名.列名</span><br><span class="line">    		id = db.Column(&#x27;user_id&#x27;, db.Integer, db.ForeignKey(&#x27;user_basic.user_id&#x27;), primary_key=True, doc=&#x27;用户ID&#x27;)</span><br><span class="line">    	主表指定relation  模型名  一对多uselist为true</span><br><span class="line">    		profile = db.relation(&#x27;UserProfile&#x27;, uselist=False)</span><br><span class="line">    2. 使用primaryjoin</span><br><span class="line">    	followings = db.relationship(&#x27;Relation&#x27;, primaryjoin=&#x27;User.id==foreign(Relation.user_id)&#x27;)</span><br><span class="line">    3. 指定字段关联查询 查询时两张表的数据以某个模型类为主进行查询，先进行字段关联</span><br><span class="line">    	target_user = db.relationship(&#x27;User&#x27;, primaryjoin=&#x27;Relation.target_user_id==foreign(User.id)&#x27;, uselist=False)</span><br><span class="line">    	Relation.query.join(Relation.target_user).options(load_only(Relation.target_user_id), contains_eager(Relation.target_user).load_only(User.name)).all()   </span><br></pre></td></tr></table></figure>

<h2 id="事务"><a href="#事务" class="headerlink" title="事务"></a>事务</h2><p>flask(上下文环境中)默认都开启了事务,db.session的add记录操作，commit事务提交，rollback回滚,每个视图开始时就进行了一个事务</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line">environ = &#123;&#x27;wsgi.version&#x27;:(1,0), &#x27;wsgi.input&#x27;: &#x27;&#x27;, &#x27;REQUEST_METHOD&#x27;: &#x27;GET&#x27;, &#x27;PATH_INFO&#x27;: &#x27;/&#x27;, &#x27;SERVER_NAME&#x27;: &#x27;itcast server&#x27;, &#x27;wsgi.url_scheme&#x27;: &#x27;http&#x27;, &#x27;SERVER_PORT&#x27;: &#x27;80&#x27;&#125;</span><br><span class="line"></span><br><span class="line">with app.request_context(environ):</span><br><span class="line">    try:</span><br><span class="line">        user = User(mobile=&#x27;18911111111&#x27;, name=&#x27;itheima&#x27;)</span><br><span class="line">        db.session.add(user)</span><br><span class="line">        db.session.flush() # 刷新事务中的数据，这样能拿到user创建之后的id</span><br><span class="line">        profile = UserProfile(id=user.id)</span><br><span class="line">        db.session.add(profile)</span><br><span class="line">        db.session.commit()</span><br><span class="line">    except:</span><br><span class="line">        db.session.rollback()</span><br></pre></td></tr></table></figure>

<h2 id="flask-marshmallow"><a href="#flask-marshmallow" class="headerlink" title="flask-marshmallow"></a>flask-marshmallow</h2><p>安装</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">pip install flask-marshmallow</span><br></pre></td></tr></table></figure>

<p>定义schema用作序列化和反序列化</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line">class UserSchema(ma.SQLAlchemyAutoSchema):</span><br><span class="line">    id = ma.auto_field()</span><br><span class="line">    name = ma.auto_field()</span><br><span class="line">    gender = ma.auto_field()</span><br><span class="line">    phone = ma.auto_field()</span><br><span class="line">    description_info = ma.auto_field()</span><br><span class="line">    # grade_ids = ma.HyperlinkRelated(&#x27;Grade&#x27;)</span><br><span class="line"></span><br><span class="line">    class Meta:</span><br><span class="line">        model = Student</span><br><span class="line">        load_instance = True</span><br></pre></td></tr></table></figure>

<p>接口使用</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br></pre></td><td class="code"><pre><span class="line">class StudentView(Resource):</span><br><span class="line"></span><br><span class="line">    def get(self):</span><br><span class="line">        users = Student.query.all()</span><br><span class="line">        user_schema = UserSchema(many=True)</span><br><span class="line">        output = user_schema.dumps(users)</span><br><span class="line">        out_put = json.loads(output)</span><br><span class="line">        return jsonify(&#123;&#x27;users&#x27;: out_put&#125;)</span><br><span class="line"></span><br><span class="line">    def post(self):</span><br><span class="line">        data = dict(request.form)</span><br><span class="line">        user_schema = UserSchema()</span><br><span class="line">        student = user_schema.loads(json.dumps(data))</span><br><span class="line">        db.session.add(student)</span><br><span class="line">        db.session.commit()</span><br><span class="line">        output = user_schema.dumps(student)</span><br><span class="line">        return jsonify(&#123;&#x27;users&#x27;: output&#125;)</span><br></pre></td></tr></table></figure>

<h2 id="Flask-Mail"><a href="#Flask-Mail" class="headerlink" title="Flask-Mail"></a>Flask-Mail</h2><p>安装</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">pip install flask-mail</span><br></pre></td></tr></table></figure>

<p>简单使用</p>
<figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">from</span> flask_mail <span class="keyword">import</span> Mail, Message</span><br><span class="line"></span><br><span class="line">app = Flask(__name__, static_url_path=<span class="string">&#x27;/&#x27;</span>)</span><br><span class="line"></span><br><span class="line"><span class="comment"># 配置MAIL设置</span></span><br><span class="line">app.config.update(</span><br><span class="line">    MAIL_SERVER=<span class="string">&#x27;smtp.qq.com&#x27;</span>,</span><br><span class="line">    MAIL_PORT=<span class="number">465</span>,</span><br><span class="line">    MAIL_USE_TLS=<span class="literal">False</span>,</span><br><span class="line">    MAIL_USE_SSL=<span class="literal">True</span>,</span><br><span class="line">    MAIL_USERNAME=<span class="string">&#x27;xxx@xx.com&#x27;</span>,</span><br><span class="line">    MAIL_PASSWORD=<span class="string">&#x27;xxx&#x27;</span>,</span><br><span class="line">)</span><br><span class="line"></span><br><span class="line">mail = Mail(app)</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="meta">@app.route(<span class="params"><span class="string">&#x27;/&#x27;</span></span>)</span></span><br><span class="line"><span class="function"><span class="keyword">def</span> <span class="title">send</span>():</span></span><br><span class="line">    <span class="keyword">try</span>:</span><br><span class="line">        <span class="comment"># 登陆成功发送邮箱</span></span><br><span class="line">        msg = Message(<span class="string">&#x27;hello&#x27;</span>, sender=<span class="string">&#x27;xx@x.com&#x27;</span>,</span><br><span class="line">                      recipients=[<span class="string">&#x27;xxx@xx.com&#x27;</span>])</span><br><span class="line">        msg.body = <span class="string">&#x27;你好，谢谢登录&#x27;</span></span><br><span class="line">        mail.connect()</span><br><span class="line">        mail.send(msg)</span><br><span class="line">        <span class="keyword">return</span> <span class="string">&#x27;成功&#x27;</span></span><br><span class="line">    <span class="keyword">except</span> Exception <span class="keyword">as</span> e:</span><br><span class="line">        <span class="keyword">return</span> e</span><br></pre></td></tr></table></figure>

<h2 id="gunicorn简单使用"><a href="#gunicorn简单使用" class="headerlink" title="gunicorn简单使用"></a>gunicorn简单使用</h2><p>安装</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">pip install gunicorn</span><br></pre></td></tr></table></figure>

<p>帮助信息</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">gunicorn -h</span><br></pre></td></tr></table></figure>


    </div>

    
    
    
        

<div>
<ul class="post-copyright">
  <li class="post-copyright-author">
    <strong>本文作者： </strong>二扬
  </li>
  <li class="post-copyright-link">
    <strong>本文链接：</strong>
    <a href="https://eryangz.gitee.io/20211120/FLASK%E5%B8%B8%E7%94%A8%E5%BA%93%E5%92%8C%E6%8F%92%E4%BB%B6/" title="FLASK常用库和插件">https://eryangz.gitee.io/20211120/FLASK常用库和插件/</a>
  </li>
  <li class="post-copyright-license">
    <strong>版权声明： </strong>本博客所有文章除特别声明外，均采用 <a href="https://creativecommons.org/licenses/by-nc-sa/4.0/" rel="noopener" target="_blank"><i class="fa fa-fw fa-creative-commons"></i>BY-NC-SA</a> 许可协议。转载请注明出处！
  </li>
</ul>
</div>


      <footer class="post-footer">
          
          <div class="post-tags">
              <a href="/tags/flask/" rel="tag"><i class="fa fa-tag"></i> flask</a>
          </div>

        


        
    <div class="post-nav">
      <div class="post-nav-item">
    <a href="/20211120/%E6%9E%81%E5%85%B6%E5%A5%BD%E7%94%A8%E7%9A%84Python%E6%A8%A1%E5%9D%97/" rel="prev" title="极其好用的Python模块">
      <i class="fa fa-chevron-left"></i> 极其好用的Python模块
    </a></div>
      <div class="post-nav-item"></div>
    </div>
      </footer>
    
  </article>
  
  
  



          </div>
          

<script>
  window.addEventListener('tabs:register', () => {
    let { activeClass } = CONFIG.comments;
    if (CONFIG.comments.storage) {
      activeClass = localStorage.getItem('comments_active') || activeClass;
    }
    if (activeClass) {
      let activeTab = document.querySelector(`a[href="#comment-${activeClass}"]`);
      if (activeTab) {
        activeTab.click();
      }
    }
  });
  if (CONFIG.comments.storage) {
    window.addEventListener('tabs:click', event => {
      if (!event.target.matches('.tabs-comment .tab-content .tab-pane')) return;
      let commentClass = event.target.classList[1];
      localStorage.setItem('comments_active', commentClass);
    });
  }
</script>

        </div>
          
  
  <div class="toggle sidebar-toggle">
    <span class="toggle-line toggle-line-first"></span>
    <span class="toggle-line toggle-line-middle"></span>
    <span class="toggle-line toggle-line-last"></span>
  </div>

  <aside class="sidebar">
    <div class="sidebar-inner">

      <ul class="sidebar-nav motion-element">
        <li class="sidebar-nav-toc">
          文章目录
        </li>
        <li class="sidebar-nav-overview">
          站点概览
        </li>
      </ul>

      <!--noindex-->
      <div class="post-toc-wrap sidebar-panel">
          <div class="post-toc motion-element"><ol class="nav"><li class="nav-item nav-level-1"><a class="nav-link" href="#FLASK%E5%B8%B8%E7%94%A8%E5%BA%93%E5%92%8C%E6%8F%92%E4%BB%B6"><span class="nav-text">FLASK常用库和插件</span></a><ol class="nav-child"><li class="nav-item nav-level-2"><a class="nav-link" href="#JWT%E8%AE%A4%E8%AF%81"><span class="nav-text">JWT认证</span></a><ol class="nav-child"><li class="nav-item nav-level-3"><a class="nav-link" href="#JSON-Web-Token%EF%BC%88JWT%EF%BC%89%E6%98%AF%E4%B8%80%E4%B8%AA%E9%9D%9E%E5%B8%B8%E8%BD%BB%E5%B7%A7%E7%9A%84%E8%A7%84%E8%8C%83%E3%80%82%E8%BF%99%E4%B8%AA%E8%A7%84%E8%8C%83%E5%85%81%E8%AE%B8%E6%88%91%E4%BB%AC%E4%BD%BF%E7%94%A8JWT%E5%9C%A8%E4%B8%A4%E4%B8%AA%E7%BB%84%E7%BB%87%E4%B9%8B%E9%97%B4%E4%BC%A0%E9%80%92%E5%AE%89%E5%85%A8%E5%8F%AF%E9%9D%A0%E7%9A%84%E4%BF%A1%E6%81%AF%E3%80%82JSON-Web-Signature%E6%98%AF%E4%B8%80%E4%B8%AA%E6%9C%89%E7%9D%80%E7%AE%80%E5%8D%95%E7%9A%84%E7%BB%9F%E4%B8%80%E8%A1%A8%E8%BE%BE%E5%BD%A2%E5%BC%8F%E7%9A%84%E5%AD%97%E7%AC%A6%E4%B8%B2-Header-Payload-Signature"><span class="nav-text">JSON Web Token（JWT）是一个非常轻巧的规范。这个规范允许我们使用JWT在两个组织之间传递安全可靠的信息。JSON Web Signature是一个有着简单的统一表达形式的字符串: Header.Payload.Signature</span></a><ol class="nav-child"><li class="nav-item nav-level-5"><a class="nav-link" href="#%E5%A4%B4%E9%83%A8%EF%BC%88Header%EF%BC%89"><span class="nav-text">头部（Header）</span></a></li><li class="nav-item nav-level-5"><a class="nav-link" href="#%E8%BD%BD%E8%8D%B7%EF%BC%88PayLoad%EF%BC%89"><span class="nav-text">载荷（PayLoad）</span></a></li><li class="nav-item nav-level-5"><a class="nav-link" href="#%E7%AD%BE%E5%90%8D%EF%BC%88signature%EF%BC%89"><span class="nav-text">签名（signature）</span></a></li></ol></li></ol></li><li class="nav-item nav-level-3"><a class="nav-link" href="#JWT%E7%9A%84Python%E5%BA%93"><span class="nav-text">JWT的Python库</span></a><ol class="nav-child"><li class="nav-item nav-level-4"><a class="nav-link" href="#itsdangerous"><span class="nav-text">itsdangerous</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#pyjwt"><span class="nav-text">pyjwt</span></a></li></ol></li></ol></li><li class="nav-item nav-level-2"><a class="nav-link" href="#Flask-Script"><span class="nav-text">Flask-Script</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#Flask-migrate"><span class="nav-text">Flask-migrate</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#Flask-SQLalchemy"><span class="nav-text">Flask-SQLalchemy</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#%E4%BA%8B%E5%8A%A1"><span class="nav-text">事务</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#flask-marshmallow"><span class="nav-text">flask-marshmallow</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#Flask-Mail"><span class="nav-text">Flask-Mail</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#gunicorn%E7%AE%80%E5%8D%95%E4%BD%BF%E7%94%A8"><span class="nav-text">gunicorn简单使用</span></a></li></ol></li></ol></div>
      </div>
      <!--/noindex-->

      <div class="site-overview-wrap sidebar-panel">
        <div class="site-author motion-element" itemprop="author" itemscope itemtype="http://schema.org/Person">
    <img class="site-author-image" itemprop="image" alt="二扬"
      src="/images/avatar.jpg">
  <p class="site-author-name" itemprop="name">二扬</p>
  <div class="site-description" itemprop="description">念念不忘, 必有回响</div>
</div>
<div class="site-state-wrap motion-element">
  <nav class="site-state">
      <div class="site-state-item site-state-posts">
          <a href="/archives/">
        
          <span class="site-state-item-count">26</span>
          <span class="site-state-item-name">日志</span>
        </a>
      </div>
      <div class="site-state-item site-state-categories">
            <a href="/categories/">
          
        <span class="site-state-item-count">14</span>
        <span class="site-state-item-name">分类</span></a>
      </div>
      <div class="site-state-item site-state-tags">
            <a href="/tags/">
          
        <span class="site-state-item-count">27</span>
        <span class="site-state-item-name">标签</span></a>
      </div>
  </nav>
</div>
  <div class="links-of-author motion-element">
      <span class="links-of-author-item">
        <a href="https://github.com/EryangZzz" title="GitHub → https:&#x2F;&#x2F;github.com&#x2F;EryangZzz" rel="noopener" target="_blank"><i class="fa fa-fw fa-github"></i>GitHub</a>
      </span>
      <span class="links-of-author-item">
        <a href="https://gitee.com/" title="Gitee → https:&#x2F;&#x2F;gitee.com&#x2F;" rel="noopener" target="_blank"><i class="fa fa-fw fa-github-alt"></i>Gitee</a>
      </span>
      <span class="links-of-author-item">
        <a href="/1289256052" title="QQ → 1289256052"><i class="fa fa-fw fa-qq"></i>QQ</a>
      </span>
      <span class="links-of-author-item">
        <a href="/1289256052@qq.com" title="E-Mail → 1289256052@qq.com"><i class="fa fa-fw fa-envelope"></i>E-Mail</a>
      </span>
  </div>



<script type="text/javascript" charset="utf-8" src="/js/tagcloud.js"></script>
<script type="text/javascript" charset="utf-8" src="/js/tagcanvas.js"></script>
<div class="widget-wrap">
    <iframe frameborder="no" border="0" marginwidth="0" marginheight="0" width=330 height=110 src="//music.163.com/outchain/player?type=0&id=8435349308&auto=1&height=66"></iframe>
    <h3 class="widget-title">标签云</h3>
    <div id="myCanvasContainer" class="widget tagcloud">
        <canvas width="250" height="250" id="resCanvas" style="width=100%">
            <ul class="tag-list" itemprop="keywords"><li class="tag-list-item"><a class="tag-list-link" href="/tags/emqx/" rel="tag">emqx</a><span class="tag-list-count">1</span></li><li class="tag-list-item"><a class="tag-list-link" href="/tags/flask/" rel="tag">flask</a><span class="tag-list-count">1</span></li><li class="tag-list-item"><a class="tag-list-link" href="/tags/git/" rel="tag">git</a><span class="tag-list-count">1</span></li><li class="tag-list-item"><a class="tag-list-link" href="/tags/js/" rel="tag">js</a><span class="tag-list-count">1</span></li><li class="tag-list-item"><a class="tag-list-link" href="/tags/metaclass/" rel="tag">metaclass</a><span class="tag-list-count">1</span></li><li class="tag-list-item"><a class="tag-list-link" href="/tags/mqtt/" rel="tag">mqtt</a><span class="tag-list-count">2</span></li><li class="tag-list-item"><a class="tag-list-link" href="/tags/nginx/" rel="tag">nginx</a><span class="tag-list-count">2</span></li><li class="tag-list-item"><a class="tag-list-link" href="/tags/odoo/" rel="tag">odoo</a><span class="tag-list-count">10</span></li><li class="tag-list-item"><a class="tag-list-link" href="/tags/odoo%E5%89%8D%E7%AB%AF/" rel="tag">odoo前端</a><span class="tag-list-count">1</span></li><li class="tag-list-item"><a class="tag-list-link" href="/tags/odoo%E9%83%A8%E7%BD%B2/" rel="tag">odoo部署</a><span class="tag-list-count">1</span></li><li class="tag-list-item"><a class="tag-list-link" href="/tags/office%E9%A2%84%E8%A7%88/" rel="tag">office预览</a><span class="tag-list-count">1</span></li><li class="tag-list-item"><a class="tag-list-link" href="/tags/pgsql/" rel="tag">pgsql</a><span class="tag-list-count">1</span></li><li class="tag-list-item"><a class="tag-list-link" href="/tags/pip%E6%BA%90/" rel="tag">pip源</a><span class="tag-list-count">1</span></li><li class="tag-list-item"><a class="tag-list-link" href="/tags/pyinstaller/" rel="tag">pyinstaller</a><span class="tag-list-count">1</span></li><li class="tag-list-item"><a class="tag-list-link" href="/tags/python/" rel="tag">python</a><span class="tag-list-count">9</span></li><li class="tag-list-item"><a class="tag-list-link" href="/tags/re/" rel="tag">re</a><span class="tag-list-count">1</span></li><li class="tag-list-item"><a class="tag-list-link" href="/tags/rtsp/" rel="tag">rtsp</a><span class="tag-list-count">1</span></li><li class="tag-list-item"><a class="tag-list-link" href="/tags/time%E6%A8%A1%E5%9D%97/" rel="tag">time模块</a><span class="tag-list-count">1</span></li><li class="tag-list-item"><a class="tag-list-link" href="/tags/ubuntu/" rel="tag">ubuntu</a><span class="tag-list-count">4</span></li><li class="tag-list-item"><a class="tag-list-link" href="/tags/ubuntu%E6%BA%90/" rel="tag">ubuntu源</a><span class="tag-list-count">1</span></li><li class="tag-list-item"><a class="tag-list-link" href="/tags/%E5%85%83%E7%B1%BB/" rel="tag">元类</a><span class="tag-list-count">1</span></li><li class="tag-list-item"><a class="tag-list-link" href="/tags/%E5%A4%9A%E7%BA%BF%E7%A8%8B/" rel="tag">多线程</a><span class="tag-list-count">2</span></li><li class="tag-list-item"><a class="tag-list-link" href="/tags/%E6%9C%8D%E5%8A%A1%E9%85%8D%E7%BD%AE/" rel="tag">服务配置</a><span class="tag-list-count">6</span></li><li class="tag-list-item"><a class="tag-list-link" href="/tags/%E6%AD%A3%E5%88%99%E8%A1%A8%E8%BE%BE%E5%BC%8F/" rel="tag">正则表达式</a><span class="tag-list-count">1</span></li><li class="tag-list-item"><a class="tag-list-link" href="/tags/%E7%AC%91%E8%84%B8%E4%BA%A4%E4%BA%92/" rel="tag">笑脸交互</a><span class="tag-list-count">1</span></li><li class="tag-list-item"><a class="tag-list-link" href="/tags/%E8%A7%86%E9%A2%91%E6%B5%81/" rel="tag">视频流</a><span class="tag-list-count">1</span></li><li class="tag-list-item"><a class="tag-list-link" href="/tags/%E8%AE%BE%E8%AE%A1%E6%A8%A1%E5%BC%8F/" rel="tag">设计模式</a><span class="tag-list-count">1</span></li></ul>
        </canvas>
    </div>
</div>




      </div>

    </div>
  </aside>
  <div id="sidebar-dimmer"></div>


      </div>
    </main>

    <footer class="footer">
      <div class="footer-inner">
        

        

<div class="copyright">
  
  &copy; 
  <span itemprop="copyrightYear">2023</span>
  <span class="with-love">
    <i class="fa fa-user"></i>
  </span>
  <span class="author" itemprop="copyrightHolder">二扬</span>
    <span class="post-meta-divider">|</span>
    <span class="post-meta-item-icon">
      <i class="fa fa-area-chart"></i>
    </span>
      <span class="post-meta-item-text">站点总字数：</span>
    <span title="站点总字数">105k</span>
    <span class="post-meta-divider">|</span>
    <span class="post-meta-item-icon">
      <i class="fa fa-coffee"></i>
    </span>
      <span class="post-meta-item-text">站点阅读时长 &asymp;</span>
    <span title="站点阅读时长">1:35</span>
</div>



        








      </div>
    </footer>
  </div>

  
  <script src="/lib/anime.min.js"></script>
  <script src="/lib/velocity/velocity.min.js"></script>
  <script src="/lib/velocity/velocity.ui.min.js"></script>

<script src="/js/utils.js"></script>

<script src="/js/motion.js"></script>


<script src="/js/schemes/pisces.js"></script>


<script src="/js/next-boot.js"></script>




  
  <script>
    (function(){
      var bp = document.createElement('script');
      var curProtocol = window.location.protocol.split(':')[0];
      bp.src = (curProtocol === 'https') ? 'https://zz.bdstatic.com/linksubmit/push.js' : 'http://push.zhanzhang.baidu.com/push.js';
      var s = document.getElementsByTagName("script")[0];
      s.parentNode.insertBefore(bp, s);
    })();
  </script>
<script>
(function(){
var bp = document.createElement('script');
var curProtocol = window.location.protocol.split(':')[0];
if (curProtocol === 'https') {
bp.src = 'https://zz.bdstatic.com/linksubmit/push.js';
}
else {
bp.src = 'http://push.zhanzhang.baidu.com/push.js';
}
 var s = document.getElementsByTagName("script")[0];
s.parentNode.insertBefore(bp, s);
})();
</script>





  
<script src="/js/local-search.js"></script>













  

  

</body>
</html>
